package com.dingding.service;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.GifCaptcha;
import cn.hutool.captcha.generator.RandomGenerator;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dingding.common.Constants;
import com.dingding.entity.request.user.*;
import com.dingding.entity.BasePageResponse;
import com.dingding.entity.BaseResponse;
import com.dingding.entity.response.user.*;
import com.dingding.entity.*;
import com.dingding.enums.*;
import com.dingding.mapper.*;
import com.dingding.utils.SessionUserUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import java.util.*;

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class UserService {

    private final UserMapper userMapper;

    private final RedisService redisService;

    private final JwtService jwtService;

    /**
     * 登录提交
     *
     * @author DingXintao
     * @date 2023/8/23 15:17
     * @param req
     * @return com.marketingtool.controller.response.user.LoginResponse
     **/
    public BaseResponse<LoginResponse> login(LoginRequest req) throws Exception {

        String captch = redisService.getCaptch(req.getKey());
        redisService.delCaptch(req.getKey());
        if (Objects.isNull(captch) || !Objects.equals(captch, req.getValidateCode())) {
            return new BaseResponse(ResponseCode.VERIFY_PICTURE_CAPTCH_ERROR);
        }

        User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getPhone, req.getPhoneEmail()));

        UserSession userVo = new UserSession();
        BeanUtils.copyProperties(user, userVo);

        String token = jwtService.getToken(userVo);

        LoginResponse res = new LoginResponse();
        res.setUserId(user.getId());
        res.setName(user.getName());
        res.setToken(token);
        return new BaseResponse(ResponseCode.SUCCESS, res);
    }

    /**
     * 验证码
     *
     * @author DingXintao
     * @date 2023/10/18 9:53
     * @return com.dingding.entity.response.user.CaptchResponse
     **/
    public CaptchResponse captch() {
        GifCaptcha gif = CaptchaUtil.createGifCaptcha(200, 100);
        RandomGenerator randomGenerator = new RandomGenerator("0123456789", 4);
        gif.setGenerator(randomGenerator);
        // 重新生成code
        gif.createCode();

        String text = gif.getCode();
        String base64 = gif.getImageBase64Data();
        String uuid = UUID.randomUUID().toString();

        log.info("uuid={}, text={}", uuid, text);

        boolean success = redisService.setCaptch(uuid, text);
        if (!success) {
            return null;
        }

        CaptchResponse res = new CaptchResponse();
        res.setText(base64);
        res.setKey(uuid);
        return res;
    }

    public void logout() {
        UserSession user = SessionUserUtil.get();
        redisService.delKey(String.format(Constants.REDIS_KEY_TOKEN, user.getUserId()));
    }

    /**
     * 获取用户信息：姓名，邮箱，企业，工号，省，头像地址
     *
     * @author DingXintao
     * @date 2023/8/23 11:35
     * @return com.marketingtool.controller.response.user.EncryptResponse
     **/
    public UserInfoResponse info() {
        UserSession user = SessionUserUtil.get();

        User user_ = userMapper.selectById(user.getUserId());

        UserInfoResponse resp = new UserInfoResponse();
        BeanUtils.copyProperties(user_, resp);

        return resp;
    }



    /**
     * 查询用户列表
     *
     * @author DingXintao
     * @date 2023/9/11 10:54
     * @param req
     * @return com.marketingtool.controller.response.BasePageResponse<java.util.List<com.marketingtool.controller.response.user.UserInfoResponse>>
     **/
    public BasePageResponse<List<UserInfoResponse>> manageUserList(UserListRequest req){
        Page<User> userPage = new Page<>(req.getPage(), req.getSize());

        List<User> records = userMapper.selectPage(userPage, new LambdaQueryWrapper<User>()
            .eq(User::getName, req.getUserName())
            .eq(User::getPhone, req.getPhoneNumber())
            ).getRecords();

        BasePageResponse res = new BasePageResponse(ResponseCode.SUCCESS);
        res.setData(records);
        res.setTotalPage(userPage.getPages());
        res.setCurrentPage(userPage.getCurrent());
        res.setTotalNum(userPage.getTotal());
        return res;
    }

    /**
     * 删除用户列表
     *
     * @author DingXintao
     * @date 2023/9/11 14:33
     * @param deleteIds
     * @return com.marketingtool.controller.response.BaseResponse
     **/
    public BaseResponse manageUserListDelete(String[] deleteIds){

        User updates_ = new User();
        updates_.setIsDeleted(1);
        userMapper.update(updates_, new LambdaQueryWrapper<User>().in(User::getId, deleteIds));

        return new BaseResponse(ResponseCode.SUCCESS);
    }

    /**
     * 用户 修改+新增
     *
     * @author DingXintao
     * @date 2023/9/11 14:33
     * @param req
     * @return com.marketingtool.controller.response.BaseResponse
     **/
    @Transactional
    public BaseResponse<UserInfoResponse> manageUserUpdate(UserUpdateRequest req) {
        // 更新用户信息
        User update = new User();
        update.setId(req.getId());
        update.setName(req.getUserName());
        update.setPhone(req.getPhoneNumber());
        User exist = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getPhone, req.getPhoneNumber()));
        if(update.getId() == null){
            Assert.isNull(exist, "手机号码已存在");
            userMapper.insert(update);
        }else{
            Assert.isTrue((exist == null || Objects.equals(req.getId(), exist.getId())), "手机号码已存在");
            userMapper.updateById(update);
        }

        UserInfoResponse vo = new UserInfoResponse();
        BeanUtils.copyProperties(req, vo);
        return new BaseResponse(ResponseCode.SUCCESS, vo);
    }

}
